package com.cal.utms.model.dayEnd;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang.time.DateUtils;

import com.cal.utms.action.user_maintenance.LoginAction;
import com.cal.utms.dao.dayEnd.DayEndDao;
import com.cal.utms.dao.maintenance.NewFundDao;
import com.cal.utms.dto.dayEnd.DayEndDto;
import com.cal.utms.entity.DailyFigure;
import com.cal.utms.entity.Deal;
import com.cal.utms.entity.DealDailyInterest;
import com.cal.utms.entity.Fund;
import com.cal.utms.entity.Instrument;
import com.cal.utms.entity.MoneyTransaction;
import com.cal.utms.valuation.FixedDepositeCalculator;
import com.cal.utms.valuation.PurchaseCalculator;
import com.cal.utms.valuation.RepoDealCalculator;
import com.cal.utms.valuation.ReverseRepoCalculator;

public class DayEndModel {
	List<DealDailyInterest> dealDailyIntList;
	List<MoneyTransaction> moneyTransList;
	List<MoneyTransaction> newMoneyTransList;
	double newPortfolio = 0;
	double totalUnits = 0;
	double newUnitPrice = 0;
	double custodianFee = 0;
	double trusteeFee = 0;
	double managementFee = 0;
	double auditFee = 0;
	double outPerformance = 0;
	double otherFeePer = 0;
	double otherFixedAnnualFee = 0;
	double otherFixedMonthlyFee = 0;
	
	
	public synchronized void runDayEndProcess(Fund fund, Date valueDate, DayEndDto dayEndDto){
		Date today = DateUtils.truncate(new Date(), Calendar.DATE);
		System.out.println("Today: "+today);
		if(fund.getUpdateDate()==null){
			dayEndDto.setStatus("Last Updated Date not available for the fund : "+fund.getFundCode());
			dayEndDto.setSuccess(false);
			return;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(DateUtils.truncate(fund.getUpdateDate(), Calendar.DATE));
		c.add(Calendar.DATE, 1);
		System.out.println("Value Date : "+valueDate);
		System.out.println("Last Up : "+fund.getUpdateDate());
		System.out.println("Last Up : "+DateUtils.truncate(fund.getUpdateDate(), Calendar.DATE));
		System.out.println("NextEOD : "+c.getTime());
		if(!DateUtils.isSameDay(c.getTime(), valueDate)){
			System.out.println("Date Mismatch! Next DayEnd Date for the fund "+fund.getFundCode()+" is "+c.getTime());
			dayEndDto.setStatus("Next DayEnd Operation Date for the fund "+fund.getFundCode()+" is "+c.getTime());
			dayEndDto.setSuccess(false);
			return;
		}
		DailyFigure dailyFigure = new DailyFigure();
		dailyFigure.setDate(valueDate);
		dailyFigure.setFund(fund);
		
		DayEndDao dayEndDao = new DayEndDao();
		
		dealDailyIntList = new ArrayList<DealDailyInterest>();
		
		calculateFixedDepositeValues(fund.getId(), valueDate, dayEndDao);
		calculateReverseRepoValues(fund.getId(), valueDate, dayEndDao);
		calculateRepoValues(fund.getId(), valueDate, dayEndDao);
		List<Deal> purchaseList = dayEndDao.getRunningDealList(fund.getId(), valueDate, "PURCH");
		calculatePurchaseDealValues(fund.getId(), valueDate, purchaseList);
		
/*		moneyTransList = dayEndDao.getDailyMoneyTransForFund(fund, valueDate, dayEndDto);
		if(moneyTransList==null){
			System.out.println("Cannot get MoneyTransactions for DayEnd for Fund:"+fund.getFundCode()+" for "+valueDate);
		}else if(moneyTransList.isEmpty()){
			System.out.println("No MoneyTransactions found at the DayEnd for Fund:"+fund.getFundCode()+" for "+valueDate);
		}*/
		
		
		double currentPortfolio = fund.getPortfolio().doubleValue();
		newPortfolio = 0;
		
		System.out.println("Calculating new PortFolio Value");
		System.out.format("Current Portfolio: \t\t\t %- 10.4f\n", currentPortfolio);
		System.out.println("-----------------------------------------------------");
		for(DealDailyInterest ddi : dealDailyIntList){
			System.out.format("Current Price of deal: %s \t %- 10.4f\n", ddi.getDeal().getDealCode(), ddi.getMarketValue().doubleValue());
			newPortfolio += ddi.getMarketValue().doubleValue();
		}
		
		double cashBalance = dayEndDao.getMoneyTransSumForEod(fund.getId(), valueDate);
		
		if(cashBalance<0){
			System.out.println("Cannot get CashBalance from MoneyTransactions for DayEnd for Fund:"+fund.getFundCode()+" for "+valueDate);
		}else{
			System.out.format("Cash Balance-Money Transactions:\t %- 10.4f\n", cashBalance);
			newPortfolio += cashBalance;
		}
		
/*		if(moneyTransList==null){
			System.out.println("Cannot get MoneyTransactions for DayEnd for Fund:"+fund.getFundCode()+" for "+valueDate);
		}else{
			for(MoneyTransaction mt : moneyTransList){
				System.out.format("Money Transactions (%s): \t\t %- 10.4f\n", mt.getTranType()+":"+mt.getTranTypeId(), mt.getTranAmont().doubleValue());
				newPortfolio += mt.getTranAmont().doubleValue();
			}
		}*/
		
		System.out.println("-----------------------------------------------------");
		System.out.format("New Portfolio: \t\t\t\t %- 10.4f\n", newPortfolio);
		BigDecimal newPortfolioObj = new BigDecimal(newPortfolio);
		dailyFigure.setPortfolioValue(newPortfolioObj);
		fund.setPortfolio(newPortfolioObj);
		
		totalUnits = dayEndDao.getUnitSumForEod(fund.getId(), valueDate);
		System.out.format("Total Units: \t\t\t\t %- 10.4f\n", totalUnits);
		
		newUnitPrice = newPortfolio/totalUnits;
		BigDecimal newUnitPriceObj = new BigDecimal(newUnitPrice);
		dailyFigure.setUnitvalue(newUnitPriceObj);
		fund.setUnitValue(newUnitPriceObj);
		
		
		System.out.format("New UnitPrice: \t\t\t\t %- 10.4f\n", newUnitPrice);
		
		
		int daysInMonth = c.getActualMaximum(Calendar.DAY_OF_MONTH);
		int daysInYear = c.getActualMaximum(Calendar.DAY_OF_YEAR);
		c.add(Calendar.DATE, 1);
		Date nextValueDate = c.getTime();
		
		
		//FEE Calculations
		newMoneyTransList = new ArrayList<MoneyTransaction>();
		
		if(fund.getCustodianFeeType().equals("percent")){
			custodianFee = newPortfolio*fund.getCustodianFee().doubleValue()/(daysInYear*100);
		}else if(fund.getCustodianFeeType().equals("fixed,monthly")){
			custodianFee = fund.getCustodianFee().doubleValue()/daysInMonth;
		}else if(fund.getCustodianFeeType().equals("fixed,annual")){
			custodianFee = fund.getCustodianFee().doubleValue()/daysInYear;
		}else{
			System.out.println("Invalid Custodian Fee type:"+fund.getCustodianFeeType());
		}
		BigDecimal custodianFeeObj = new BigDecimal(custodianFee);
		dailyFigure.setCustodianFee(custodianFeeObj);
		MoneyTransaction moneyTransactionDebit = new MoneyTransaction();
		moneyTransactionDebit.setCreditDebit("D");
		moneyTransactionDebit.setCustomerType("FUN");
		moneyTransactionDebit.setDate(today);
		moneyTransactionDebit.setEffectDate(nextValueDate);
		moneyTransactionDebit.setFund(fund);
		moneyTransactionDebit.setTranAmont(new BigDecimal(custodianFee*(-1)));
		moneyTransactionDebit.setTranTo(fund.getId());
		moneyTransactionDebit.setTranType("EOD");
		moneyTransactionDebit.setTranTypeId(fund.getId());
		// moneyTransactionDebit.setUser(LoginAction.getCurrentLogingUser());
		newMoneyTransList.add(moneyTransactionDebit);
		
		MoneyTransaction moneyTransactionCredit = new MoneyTransaction();
		moneyTransactionCredit.setCreditDebit("C");
		moneyTransactionCredit.setCustomerType("FEEC");
		moneyTransactionCredit.setDate(today);
		moneyTransactionCredit.setEffectDate(nextValueDate);
		moneyTransactionCredit.setFund(fund);
		moneyTransactionCredit.setTranAmont(custodianFeeObj);
		moneyTransactionCredit.setTranTo(fund.getCustodian().getId());
		moneyTransactionCredit.setTranType("EOD");
		moneyTransactionCredit.setTranTypeId(fund.getId());
		// moneyTransactionCredit.setUser(LoginAction.getCurrentLogingUser());
		newMoneyTransList.add(moneyTransactionCredit);
		
		if(fund.getTrusteeFeeType().equals("percent")){
			trusteeFee = newPortfolio*fund.getTrusteeFee().doubleValue()/(daysInYear*100);
		}else if(fund.getTrusteeFeeType().equals("fixed,monthly")){
			trusteeFee = fund.getTrusteeFee().doubleValue()/daysInMonth;
		}else if(fund.getTrusteeFeeType().equals("fixed,annual")){
			trusteeFee = fund.getTrusteeFee().doubleValue()/daysInYear;
		}else{
			System.out.println("Invalid Trustee Fee type:"+fund.getTrusteeFeeType());
		}
		BigDecimal trusteeFeeObj = new BigDecimal(trusteeFee);
		dailyFigure.setTrusteeFee(trusteeFeeObj);
		moneyTransactionDebit = new MoneyTransaction();
		moneyTransactionDebit.setCreditDebit("D");
		moneyTransactionDebit.setCustomerType("FUN");
		moneyTransactionDebit.setDate(today);
		moneyTransactionDebit.setEffectDate(nextValueDate);
		moneyTransactionDebit.setFund(fund);
		moneyTransactionDebit.setTranAmont(new BigDecimal(trusteeFee*(-1)));
		moneyTransactionDebit.setTranTo(fund.getId());
		moneyTransactionDebit.setTranType("EOD");
		moneyTransactionDebit.setTranTypeId(fund.getId());
		// moneyTransactionDebit.setUser(LoginAction.getCurrentLogingUser());
		newMoneyTransList.add(moneyTransactionDebit);
		
		moneyTransactionCredit = new MoneyTransaction();
		moneyTransactionCredit.setCreditDebit("C");
		moneyTransactionCredit.setCustomerType("FEET");
		moneyTransactionCredit.setDate(today);
		moneyTransactionCredit.setEffectDate(nextValueDate);
		moneyTransactionCredit.setFund(fund);
		moneyTransactionCredit.setTranAmont(trusteeFeeObj);
		moneyTransactionCredit.setTranTo(fund.getCustodian().getId());
		moneyTransactionCredit.setTranType("EOD");
		moneyTransactionCredit.setTranTypeId(fund.getId());
		// moneyTransactionCredit.setUser(LoginAction.getCurrentLogingUser());
		newMoneyTransList.add(moneyTransactionCredit);
		
		if(fund.getManagementFeeType().equals("percent")){
			managementFee = newPortfolio*fund.getManagementFee().doubleValue()/(daysInYear*100);
		}else if(fund.getManagementFeeType().equals("fixed,monthly")){
			managementFee = fund.getManagementFee().doubleValue()/daysInMonth;
		}else if(fund.getManagementFeeType().equals("fixed,annual")){
			managementFee = fund.getManagementFee().doubleValue()/daysInYear;
		}else{
			System.out.println("Invalid Management Fee type:"+fund.getManagementFeeType());
		}
		BigDecimal managementFeeObj = new BigDecimal(managementFee);
		dailyFigure.setManagementFee(managementFeeObj);
		moneyTransactionDebit = new MoneyTransaction();
		moneyTransactionDebit.setCreditDebit("D");
		moneyTransactionDebit.setCustomerType("FUN");
		moneyTransactionDebit.setDate(today);
		moneyTransactionDebit.setEffectDate(nextValueDate);
		moneyTransactionDebit.setFund(fund);
		moneyTransactionDebit.setTranAmont(new BigDecimal(managementFee*(-1)));
		moneyTransactionDebit.setTranTo(fund.getId());
		moneyTransactionDebit.setTranType("EOD");
		moneyTransactionDebit.setTranTypeId(fund.getId());
		// moneyTransactionDebit.setUser(LoginAction.getCurrentLogingUser());
		newMoneyTransList.add(moneyTransactionDebit);
		
		moneyTransactionCredit = new MoneyTransaction();
		moneyTransactionCredit.setCreditDebit("C");
		moneyTransactionCredit.setCustomerType("FEEM");
		moneyTransactionCredit.setDate(today);
		moneyTransactionCredit.setEffectDate(nextValueDate);
		moneyTransactionCredit.setFund(fund);
		moneyTransactionCredit.setTranAmont(managementFeeObj);
		moneyTransactionCredit.setTranTo(fund.getCustodian().getId());
		moneyTransactionCredit.setTranType("EOD");
		moneyTransactionCredit.setTranTypeId(fund.getId());
		// moneyTransactionCredit.setUser(LoginAction.getCurrentLogingUser());
		newMoneyTransList.add(moneyTransactionCredit);
		
		if(fund.getAuditFeeType().equals("percent")){
			auditFee = newPortfolio*fund.getAuditFee().doubleValue()/(daysInYear*100);
		}else if(fund.getAuditFeeType().equals("fixed,monthly")){
			auditFee = fund.getAuditFee().doubleValue()/daysInMonth;
		}else if(fund.getAuditFeeType().equals("fixed,annual")){
			auditFee = fund.getAuditFee().doubleValue()/daysInYear;
		}else{
			System.out.println("Invalid Audit Fee type:"+fund.getAuditFeeType());
		}
		BigDecimal auditFeeObj = new BigDecimal(auditFee);
		dailyFigure.setAuditFee(auditFeeObj);
		moneyTransactionDebit = new MoneyTransaction();
		moneyTransactionDebit.setCreditDebit("D");
		moneyTransactionDebit.setCustomerType("FUN");
		moneyTransactionDebit.setDate(today);
		moneyTransactionDebit.setEffectDate(nextValueDate);
		moneyTransactionDebit.setFund(fund);
		moneyTransactionDebit.setTranAmont(new BigDecimal(auditFee*(-1)));
		moneyTransactionDebit.setTranTo(fund.getId());
		moneyTransactionDebit.setTranType("EOD");
		moneyTransactionDebit.setTranTypeId(fund.getId());
		// moneyTransactionDebit.setUser(LoginAction.getCurrentLogingUser());
		newMoneyTransList.add(moneyTransactionDebit);
		
		moneyTransactionCredit = new MoneyTransaction();
		moneyTransactionCredit.setCreditDebit("C");
		moneyTransactionCredit.setCustomerType("FEEA");
		moneyTransactionCredit.setDate(today);
		moneyTransactionCredit.setEffectDate(nextValueDate);
		moneyTransactionCredit.setFund(fund);
		moneyTransactionCredit.setTranAmont(auditFeeObj);
		moneyTransactionCredit.setTranTo(fund.getCustodian().getId());
		moneyTransactionCredit.setTranType("EOD");
		moneyTransactionCredit.setTranTypeId(fund.getId());
		// moneyTransactionCredit.setUser(LoginAction.getCurrentLogingUser());
		newMoneyTransList.add(moneyTransactionCredit);
		
		//TODO outPerformance = 0;
		if(fund.getOtherFeePercent()!=null){
			otherFeePer = newPortfolio*fund.getOtherFeePercent().doubleValue()/(daysInYear*100);
			BigDecimal otherFeePerObj = new BigDecimal(otherFeePer);
			dailyFigure.setOtherFeePer(otherFeePerObj);
			moneyTransactionDebit = new MoneyTransaction();
			moneyTransactionDebit.setCreditDebit("D");
			moneyTransactionDebit.setCustomerType("FUN");
			moneyTransactionDebit.setDate(today);
			moneyTransactionDebit.setEffectDate(nextValueDate);
			moneyTransactionDebit.setFund(fund);
			moneyTransactionDebit.setTranAmont(new BigDecimal(otherFeePer*(-1)));
			moneyTransactionDebit.setTranTo(fund.getId());
			moneyTransactionDebit.setTranType("EOD");
			moneyTransactionDebit.setTranTypeId(fund.getId());
			// moneyTransactionDebit.setUser(LoginAction.getCurrentLogingUser());
			newMoneyTransList.add(moneyTransactionDebit);
			
			moneyTransactionCredit = new MoneyTransaction();
			moneyTransactionCredit.setCreditDebit("C");
			moneyTransactionCredit.setCustomerType("FEEOP");
			moneyTransactionCredit.setDate(today);
			moneyTransactionCredit.setEffectDate(nextValueDate);
			moneyTransactionCredit.setFund(fund);
			moneyTransactionCredit.setTranAmont(new BigDecimal(otherFeePer));
			moneyTransactionCredit.setTranTo(fund.getCustodian().getId());
			moneyTransactionCredit.setTranType("EOD");
			moneyTransactionCredit.setTranTypeId(fund.getId());
			// moneyTransactionCredit.setUser(LoginAction.getCurrentLogingUser());
			newMoneyTransList.add(moneyTransactionCredit);
		}
		
		
		if(fund.getOtherFeeMonthly()!=null){
			otherFixedMonthlyFee = fund.getOtherFeeMonthly().doubleValue()/daysInMonth;
			BigDecimal otherFixedMonthlyFeeObj = new BigDecimal(otherFixedMonthlyFee);
			dailyFigure.setOtherMonthlyFixedFee(otherFixedMonthlyFeeObj);
			moneyTransactionDebit = new MoneyTransaction();
			moneyTransactionDebit.setCreditDebit("D");
			moneyTransactionDebit.setCustomerType("FUN");
			moneyTransactionDebit.setDate(today);
			moneyTransactionDebit.setEffectDate(nextValueDate);
			moneyTransactionDebit.setFund(fund);
			moneyTransactionDebit.setTranAmont(new BigDecimal(otherFixedMonthlyFee*(-1)));
			moneyTransactionDebit.setTranTo(fund.getId());
			moneyTransactionDebit.setTranType("EOD");
			moneyTransactionDebit.setTranTypeId(fund.getId());
			// moneyTransactionDebit.setUser(LoginAction.getCurrentLogingUser());
			newMoneyTransList.add(moneyTransactionDebit);
			
			moneyTransactionCredit = new MoneyTransaction();
			moneyTransactionCredit.setCreditDebit("C");
			moneyTransactionCredit.setCustomerType("FEEOFM");
			moneyTransactionCredit.setDate(today);
			moneyTransactionCredit.setEffectDate(nextValueDate);
			moneyTransactionCredit.setFund(fund);
			moneyTransactionCredit.setTranAmont(otherFixedMonthlyFeeObj);
			moneyTransactionCredit.setTranTo(fund.getCustodian().getId());
			moneyTransactionCredit.setTranType("EOD");
			moneyTransactionCredit.setTranTypeId(fund.getId());
			// moneyTransactionCredit.setUser(LoginAction.getCurrentLogingUser());
			newMoneyTransList.add(moneyTransactionCredit);
		}
		
		
		if(fund.getOtherFeeAnnual()!=null){
			otherFixedAnnualFee = fund.getOtherFeeAnnual().doubleValue()/daysInYear;
			BigDecimal otherFixedAnnualFeeObj = new BigDecimal(otherFixedAnnualFee);
			dailyFigure.setOtherAnnualyFixedFee(otherFixedAnnualFeeObj);
			moneyTransactionDebit = new MoneyTransaction();
			moneyTransactionDebit.setCreditDebit("D");
			moneyTransactionDebit.setCustomerType("FUN");
			moneyTransactionDebit.setDate(today);
			moneyTransactionDebit.setEffectDate(nextValueDate);
			moneyTransactionDebit.setFund(fund);
			moneyTransactionDebit.setTranAmont(new BigDecimal(otherFixedAnnualFee*(-1)));
			moneyTransactionDebit.setTranTo(fund.getId());
			moneyTransactionDebit.setTranType("EOD");
			moneyTransactionDebit.setTranTypeId(fund.getId());
			// moneyTransactionDebit.setUser(LoginAction.getCurrentLogingUser());
			newMoneyTransList.add(moneyTransactionDebit);
			
			moneyTransactionCredit = new MoneyTransaction();
			moneyTransactionCredit.setCreditDebit("C");
			moneyTransactionCredit.setCustomerType("FEEOFA");
			moneyTransactionCredit.setDate(today);
			moneyTransactionCredit.setEffectDate(nextValueDate);
			moneyTransactionCredit.setFund(fund);
			moneyTransactionCredit.setTranAmont(otherFixedAnnualFeeObj);
			moneyTransactionCredit.setTranTo(fund.getCustodian().getId());
			moneyTransactionCredit.setTranType("EOD");
			moneyTransactionCredit.setTranTypeId(fund.getId());
			// moneyTransactionCredit.setUser(LoginAction.getCurrentLogingUser());
			newMoneyTransList.add(moneyTransactionCredit);
		}
		
		//Add Coupon Receivables to money transaction, if there is any coupon tomorrow
		System.out.println("Checking available coupon receivables on "+ nextValueDate);
		for(Deal purDeal : purchaseList){
			Instrument tempIns = null;
			if(purDeal.getDealInstrumentMaps()!=null && purDeal.getDealInstrumentMaps().size()==1){
				tempIns = purDeal.getDealInstrumentMaps().get(0).getInstrument();
			}
			if(tempIns==null || tempIns.getInstrumentType()==null || tempIns.getInstrumentType().getCouponAvailability()==0){
				continue;
			}else{
				PurchaseCalculator purchCal = new PurchaseCalculator();
				//purchCal.valuateEodParams(purDeal, c.getTime());
				Date nextCouponDate = purchCal.getNextCouponDate(tempIns, valueDate);
				System.out.println("deal:"+purDeal.getDealCode()+"  : nextCpn: "+nextCouponDate);
				if(nextCouponDate!=null && DateUtils.isSameDay(c.getTime(), nextCouponDate)){
					purchCal.valuateEodParams(purDeal, c.getTime());
					moneyTransactionDebit = new MoneyTransaction();
					moneyTransactionDebit.setCreditDebit("D");
					moneyTransactionDebit.setCustomerType("ISU");
					moneyTransactionDebit.setDate(today);
					moneyTransactionDebit.setEffectDate(nextValueDate);
					moneyTransactionDebit.setFund(fund);
					moneyTransactionDebit.setTranAmont(new BigDecimal((purchCal.getCouponInterest())*(-1)));
					moneyTransactionDebit.setTranTo(tempIns.getIssuer().getId());
					moneyTransactionDebit.setTranType("EOD");
					moneyTransactionDebit.setTranTypeId(fund.getId());
					// moneyTransactionDebit.setUser(LoginAction.getCurrentLogingUser());
					newMoneyTransList.add(moneyTransactionDebit);
					
					moneyTransactionCredit = new MoneyTransaction();
					moneyTransactionCredit.setCreditDebit("C");
					moneyTransactionCredit.setCustomerType("FUN");
					moneyTransactionCredit.setDate(today);
					moneyTransactionCredit.setEffectDate(nextValueDate);
					moneyTransactionCredit.setFund(fund);
					moneyTransactionCredit.setTranAmont(new BigDecimal(purchCal.getCouponInterest()));
					moneyTransactionCredit.setTranTo(fund.getId());
					moneyTransactionCredit.setTranType("EOD");
					moneyTransactionCredit.setTranTypeId(fund.getId());
					// moneyTransactionCredit.setUser(LoginAction.getCurrentLogingUser());
					newMoneyTransList.add(moneyTransactionCredit);
					System.out.println("Coupon found for deal:"+purDeal.getDealCode()+" value: "+purchCal.getCouponInterest());
				}
			}
		}
		
		//add money transactions for the deals matured on next value date
		System.out.println("Adding MoneyTrans entries for the deals matured on "+ nextValueDate);
		List<Deal> maturityDealList = dayEndDao.getMaturityDealList(fund.getId(), nextValueDate);
		for(Deal matDeal : maturityDealList){
			RepoDealCalculator repoCalculator = new RepoDealCalculator();
			PurchaseCalculator purchCalculator = new PurchaseCalculator();
			FixedDepositeCalculator fdCalculator = new FixedDepositeCalculator();
			ReverseRepoCalculator revRepoCalculator = new ReverseRepoCalculator();
			if(matDeal.getDealType().getCode().equals("REPO")){
				repoCalculator.valuateAllParameters(matDeal);
				moneyTransactionDebit = new MoneyTransaction();
				moneyTransactionDebit.setCreditDebit("D");
				moneyTransactionDebit.setCustomerType("FUN");
				moneyTransactionDebit.setDate(today);
				moneyTransactionDebit.setEffectDate(nextValueDate);
				moneyTransactionDebit.setFund(fund);
				moneyTransactionDebit.setTranAmont(new BigDecimal((repoCalculator.getMaturityValue())*(-1)));
				moneyTransactionDebit.setTranTo(fund.getId());
				moneyTransactionDebit.setTranType("EOD");
				moneyTransactionDebit.setTranTypeId(fund.getId());
				// moneyTransactionDebit.setUser(LoginAction.getCurrentLogingUser());
				newMoneyTransList.add(moneyTransactionDebit);
				
				moneyTransactionCredit = new MoneyTransaction();
				moneyTransactionCredit.setCreditDebit("C");
				moneyTransactionCredit.setCustomerType("ISU");
				moneyTransactionCredit.setDate(today);
				moneyTransactionCredit.setEffectDate(nextValueDate);
				moneyTransactionCredit.setFund(fund);
				moneyTransactionCredit.setTranAmont(new BigDecimal(repoCalculator.getMaturityValue()));
				moneyTransactionCredit.setTranTo(matDeal.getIssuer().getId());
				moneyTransactionCredit.setTranType("EOD");
				moneyTransactionCredit.setTranTypeId(fund.getId());
				// moneyTransactionCredit.setUser(LoginAction.getCurrentLogingUser());
				newMoneyTransList.add(moneyTransactionCredit);
				System.out.println("Maturity found for deal: "+matDeal.getDealCode()+" Value:"+repoCalculator.getMaturityValue());
			}else{
				double maturityVal = 0;
				if(matDeal.getDealType().getCode().equals("PURCH")){
					purchCalculator.valuateMaturityValue(matDeal);
					maturityVal = purchCalculator.getFaceValue();
					if(maturityVal<0){
						System.out.println("Maturity Value Calculation Error for deal:"+matDeal.getDealCode());
					}
				}else if(matDeal.getDealType().getCode().equals("FD")){
					fdCalculator.valuateAllParameters(matDeal);
					maturityVal = fdCalculator.getMaturityValue();
				}else if(matDeal.getDealType().getCode().equals("RREPO")){
					revRepoCalculator.valuateAllParameters(matDeal);
					maturityVal = revRepoCalculator.getMaturityValue();
				}else{
					System.out.println("Invalid Deal Type :"+matDeal.getDealType().getCode() + " found for deal:"+matDeal.getDealCode());
					maturityVal = -1;
				}
				if(maturityVal>0){
					moneyTransactionDebit = new MoneyTransaction();
					moneyTransactionDebit.setCreditDebit("D");
					moneyTransactionDebit.setCustomerType("ISU");
					moneyTransactionDebit.setDate(today);
					moneyTransactionDebit.setEffectDate(nextValueDate);
					moneyTransactionDebit.setFund(fund);
					moneyTransactionDebit.setTranAmont(new BigDecimal(maturityVal*(-1)));
					moneyTransactionDebit.setTranTo(matDeal.getIssuer().getId());
					moneyTransactionDebit.setTranType("EOD");
					moneyTransactionDebit.setTranTypeId(matDeal.getId());
					// moneyTransactionDebit.setUser(LoginAction.getCurrentLogingUser());
					newMoneyTransList.add(moneyTransactionDebit);
					
					moneyTransactionCredit = new MoneyTransaction();
					moneyTransactionCredit.setCreditDebit("C");
					moneyTransactionCredit.setCustomerType("FUN");
					moneyTransactionCredit.setDate(today);
					moneyTransactionCredit.setEffectDate(nextValueDate);
					moneyTransactionCredit.setFund(fund);
					moneyTransactionCredit.setTranAmont(new BigDecimal(maturityVal));
					moneyTransactionCredit.setTranTo(matDeal.getIssuer().getId());
					moneyTransactionCredit.setTranType("EOD");
					moneyTransactionCredit.setTranTypeId(matDeal.getId());
					// moneyTransactionCredit.setUser(LoginAction.getCurrentLogingUser());
					newMoneyTransList.add(moneyTransactionCredit);
					System.out.println("Maturity found for deal: "+matDeal.getDealCode()+" Value:"+maturityVal);
				}
			}
		}
		
		//Change deal states matured on value date
		List<Deal> maturedDealList = dayEndDao.updateMaturityDealStatus(fund.getId(), valueDate, "Matured");
		for(Deal d : maturedDealList){
			System.out.println("Deal : "+ d.getDealCode()+" matured.");
		}
		
		fund.setUpdateDate(valueDate);
		dayEndDto.setSuccess(true);
		dayEndDao.updateEodParams(fund, dailyFigure, dealDailyIntList, newMoneyTransList, dayEndDto);
/*		System.out.println("Days in month: "+daysInMonth);
		System.out.println("Days in year: "+daysInYear);

		c.set(Calendar.DATE, daysInMonth);

		Date lastDayofMonth = c.getTime();
		c.set(Calendar.YEAR,c.get(Calendar.YEAR));
	    c.set(Calendar.MONTH,11);
	    c.set(Calendar.DAY_OF_MONTH,31);
	    Date lastDayofYear = c.getTime();*/
	
	}
	
	public void calculateFixedDepositeValues(int fundId, Date valueDate, DayEndDao dayEndDao){
		System.out.println("Update FD Deal Daily Interest for the Fund :"+fundId);
		DealDailyInterest dealDailyInt = null;
		List<Deal> fdList = dayEndDao.getRunningDealList(fundId, valueDate, "FD");
		if(fdList!=null){
			FixedDepositeCalculator fdCalculator = new FixedDepositeCalculator();
			for(Deal deal : fdList){
				fdCalculator.valuateEodParams(deal, valueDate);
				dealDailyInt = new DealDailyInterest();
				dealDailyInt.setDate(valueDate);
				dealDailyInt.setDeal(deal);
				dealDailyInt.setInterest(new BigDecimal(fdCalculator.getDailyInterest()).setScale(4, BigDecimal.ROUND_HALF_UP));
				dealDailyInt.setMarketValue(new BigDecimal(fdCalculator.getMarketValueCpa()).setScale(4, BigDecimal.ROUND_HALF_UP));
				dealDailyIntList.add(dealDailyInt);
				dealDailyInt = null;				
			}
		}else{
			System.out.println("0 FD Deals Updated.");
		}
	}
	
	public void calculateReverseRepoValues(int fundId, Date valueDate, DayEndDao dayEndDao){
		System.out.println("Update Reverse REPO Deal Daily Interest for the Fund :"+fundId);
		DealDailyInterest dealDailyInt = null;
		List<Deal> repoList = dayEndDao.getRunningDealList(fundId, valueDate, "RREPO");
		if(repoList!=null){
			RepoDealCalculator repoCalculator = new RepoDealCalculator();
			for(Deal deal : repoList){
				repoCalculator.valuateEodParams(deal, valueDate);
				dealDailyInt = new DealDailyInterest();
				dealDailyInt.setDate(valueDate);
				dealDailyInt.setDeal(deal);
				dealDailyInt.setInterest(new BigDecimal(repoCalculator.getDailyInterest()).setScale(4, BigDecimal.ROUND_HALF_UP));
				dealDailyInt.setMarketValue(new BigDecimal(repoCalculator.getMarketValueCpa()).setScale(4, BigDecimal.ROUND_HALF_UP));
				dealDailyIntList.add(dealDailyInt);
				dealDailyInt = null;				
			}
		}else{
			System.out.println("0 Reverse REPO Deals Updated.");
		}
	}
	
	public void calculateRepoValues(int fundId, Date valueDate, DayEndDao dayEndDao){
		System.out.println("Update REPO Deal Daily Interest for the Fund :"+fundId);
		DealDailyInterest dealDailyInt = null;
		List<Deal> repoList = dayEndDao.getRunningDealList(fundId, valueDate, "REPO");
		if(repoList!=null){
			RepoDealCalculator repoCalculator = new RepoDealCalculator();
			for(Deal deal : repoList){
				repoCalculator.valuateEodParams(deal, valueDate);
				dealDailyInt = new DealDailyInterest();
				dealDailyInt.setDate(valueDate);
				dealDailyInt.setDeal(deal);
				dealDailyInt.setInterest(new BigDecimal(repoCalculator.getDailyInterest()).setScale(4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(-1)));
				dealDailyInt.setMarketValue(new BigDecimal(repoCalculator.getMarketValueCpa()).setScale(4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(-1)));
				dealDailyIntList.add(dealDailyInt);
				dealDailyInt = null;				
			}
		}else{
			System.out.println("0 REPO Deals Updated.");
		}
	}
	
	public void calculatePurchaseDealValues(int fundId, Date valueDate, List<Deal> purchaseList){
		System.out.println("Update Purchase Deal Daily Interest for the Fund :"+fundId);
		DealDailyInterest dealDailyInt = null;
		//List<Deal> purchaseList = dayEndDao.getRunningDealList(fundId, valueDate, "PURCH");
		if(purchaseList!=null){
			PurchaseCalculator purchCalculator = new PurchaseCalculator();
			for(Deal deal : purchaseList){
				purchCalculator.valuateEodParams(deal, valueDate);
				dealDailyInt = new DealDailyInterest();
				dealDailyInt.setDate(valueDate);
				dealDailyInt.setDeal(deal);
				dealDailyInt.setInterest(new BigDecimal(purchCalculator.getDailyInterest()).setScale(4, BigDecimal.ROUND_HALF_UP));
				dealDailyInt.setMarketValue(new BigDecimal(purchCalculator.getCostPlusMarketValue()).setScale(4, BigDecimal.ROUND_HALF_UP));
				dealDailyIntList.add(dealDailyInt);
				dealDailyInt = null;			
			}
		}else{
			System.out.println("0 Purchase Deals Updated.");
		}
	}

	public List<DealDailyInterest> getDealDailyIntList() {
		return dealDailyIntList;
	}

	public void setDealDailyIntList(List<DealDailyInterest> dealDailyIntList) {
		this.dealDailyIntList = dealDailyIntList;
	}

	public List<MoneyTransaction> getMoneyTransList() {
		return moneyTransList;
	}

	public void setMoneyTransList(List<MoneyTransaction> moneyTransList) {
		this.moneyTransList = moneyTransList;
	}

	public List<MoneyTransaction> getNewMoneyTransList() {
		return newMoneyTransList;
	}

	public void setNewMoneyTransList(List<MoneyTransaction> newMoneyTransList) {
		this.newMoneyTransList = newMoneyTransList;
	}

	public double getNewPortfolio() {
		return newPortfolio;
	}

	public void setNewPortfolio(double newPortfolio) {
		this.newPortfolio = newPortfolio;
	}

	public double getTotalUnits() {
		return totalUnits;
	}

	public void setTotalUnits(double totalUnits) {
		this.totalUnits = totalUnits;
	}

	public double getNewUnitPrice() {
		return newUnitPrice;
	}

	public void setNewUnitPrice(double newUnitPrice) {
		this.newUnitPrice = newUnitPrice;
	}

	public double getCustodianFee() {
		return custodianFee;
	}

	public void setCustodianFee(double custodianFee) {
		this.custodianFee = custodianFee;
	}

	public double getTrusteeFee() {
		return trusteeFee;
	}

	public void setTrusteeFee(double trusteeFee) {
		this.trusteeFee = trusteeFee;
	}

	public double getManagementFee() {
		return managementFee;
	}

	public void setManagementFee(double managementFee) {
		this.managementFee = managementFee;
	}

	public double getAuditFee() {
		return auditFee;
	}

	public void setAuditFee(double auditFee) {
		this.auditFee = auditFee;
	}

	public double getOutPerformance() {
		return outPerformance;
	}

	public void setOutPerformance(double outPerformance) {
		this.outPerformance = outPerformance;
	}

	public double getOtherFeePer() {
		return otherFeePer;
	}

	public void setOtherFeePer(double otherFeePer) {
		this.otherFeePer = otherFeePer;
	}

	public double getOtherFixedAnnualFee() {
		return otherFixedAnnualFee;
	}

	public void setOtherFixedAnnualFee(double otherFixedAnnualFee) {
		this.otherFixedAnnualFee = otherFixedAnnualFee;
	}

	public double getOtherFixedMonthlyFee() {
		return otherFixedMonthlyFee;
	}

	public void setOtherFixedMonthlyFee(double otherFixedMonthlyFee) {
		this.otherFixedMonthlyFee = otherFixedMonthlyFee;
	}
	
	public static void main(String[] args) throws ParseException {
		Fund fund = new NewFundDao().getById(24);
		if(fund==null){
			System.out.println("Cannot Find the Fund");
			return ;
		}
		Date valueDate = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse("2014-11-18 00:00:00");
		new DayEndModel().runDayEndProcess(fund, valueDate, new DayEndDto());
	}
	
}